package academic.ui.server;


import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.torque.NoRowsException;
import org.apache.torque.TooManyRowsException;
import org.apache.torque.TorqueException;
import org.apache.torque.util.Criteria;

import torque.generated.City;
import torque.generated.CityPeer;
import torque.generated.Customers;
import torque.generated.CustomersCity;
import torque.generated.CustomersCityPeer;
import torque.generated.CustomersPeer;
import torque.generated.Discussion;
import torque.generated.DiscussionPeer;
import torque.generated.Event;
import torque.generated.Followers;
import torque.generated.FollowersPeer;
import torque.generated.Message;
import torque.generated.Products;
import torque.generated.ProductsPeer;

import com.workingdogs.village.DataSetException;





import academic.ui.client.AppService;
import academic.ui.server.utils.GWT_CityHelper;
import ecommerce.soco.shared.GWT_City;
import ecommerce.soco.shared.GWT_Customer;
import ecommerce.soco.shared.GWT_Discussion;
import ecommerce.soco.shared.GWT_Event;
import ecommerce.soco.shared.GWT_Message;
import ecommerce.soco.shared.GWT_Product;

import ecommerce.soco.server.util.SocoCopier;
import ecommerce.soco.server.util.email.EmailUsers;

public class AppServiceImpl extends SocoGWTServlet implements AppService {

	public SocoCopier helper= new SocoCopier();
	/**
	 * 
	 */
	private static final long serialVersionUID = 8281378794464309504L;
	
	@Override
	public GWT_Customer getUser() {
		if(isLoggedIn()) {
			
			Customers customer;
			try {
				customer = CustomersPeer.retrieveByPK(getAppEng().getUserMgr().getCurrentCustomer().getCustomersId());
				
				return helper.getGWT_Customer(customer);
				
			} catch (NoRowsException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (TooManyRowsException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (TorqueException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			
		}
		return null;
	}

	public AppServiceImpl() {
		super();
	}

	
	@Override
	public GWT_Product getFullProduct(Integer id){
		if(id==-1)
			return new GWT_Product();
		
        try {
        	Products p = ProductsPeer.retrieveByPK(id);
        	getAppEng().getOrderMgr().setProduct(p);
        	return helper.getGWT_Product(p);
		} catch (NoRowsException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TooManyRowsException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TorqueException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
        return null;
	}

	
	@Override
	public Boolean isLoggedIn() {	
			return this.getAppEng().getUserMgr().isLoggedIn();
	}


	@Override
	public Boolean logout(){
		getAppEng().getUserMgr().logout();
		return true;
	}

	@Override
	public ArrayList<GWT_Product> getActiveProducts(){
		try {
			Criteria activeProductsCriteria = new Criteria();
			activeProductsCriteria.add(ProductsPeer.PRODUCTS_STATUS, "active");
			activeProductsCriteria.add(ProductsPeer.CITY_ID,getCityId());
			List<Products> activeProducts = ProductsPeer.doSelect(activeProductsCriteria);
			ArrayList<GWT_Product> products = new ArrayList<GWT_Product>();
			for(torque.generated.Products product : activeProducts)
			{
				products.add(helper.getGWT_Product(product));
			}
			return products;
		} catch (TorqueException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	private Integer getCityId() {
		return getAppEng().getCity().getCityId();
	}

	@Override
	public ArrayList<GWT_Product> getRecentProducts() {
		Criteria expProdCrit = new Criteria();
		expProdCrit.add(ProductsPeer.PRODUCTS_STATUS,(Object)"active",Criteria.NOT_EQUAL).and(ProductsPeer.CITY_ID, getCityId());
		List<Products> expiredProducts;
		try {
			expiredProducts = ProductsPeer.doSelect(expProdCrit);
		
		ArrayList<GWT_Product> products = new ArrayList<GWT_Product>();
		for(Products product : expiredProducts)
		{
			products.add(helper.getGWT_Product(product));
		}
		return products;
		} catch (TorqueException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}


	@Override
	public ArrayList<GWT_Product> getFullWithActiveProducts(Integer productID)
	{
		ArrayList<GWT_Product> products = getActiveProducts();
		int productIter=-1;
		for(int i = 0;i<products.size(); i++)
		{
			if(products.get(i).getId().intValue()==productID)
			{
				productIter=i;
			}
		}
		products.remove(productIter);
		products.add(getFullProduct(productID));
		return products;
	}

	@Override
	public ArrayList<GWT_City> getParticipatingCities(){
		try {
			return GWT_CityHelper.getCities(CityPeer.doSelect(new Criteria()));
		} catch (TorqueException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (DataSetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public Boolean updateCity(String cityId) {
		try {
			getAppEng().setCity(CityPeer.retrieveByPK(Integer.parseInt(cityId)));
		} catch (NoRowsException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (TooManyRowsException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (NumberFormatException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (TorqueException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		//save the users city preference if the user is logged in
		if(isLoggedIn())
		{
			try {
				GWT_CityHelper.saveCity(getAppEng().getUserMgr().getCurrentCustomer().getCustomersId(),Integer.parseInt(cityId));
			} catch (NumberFormatException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return false;
			} catch (TorqueException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return false;
			}
		}
		return true;
	}

	@Override
	public Boolean setCity() {
		Integer city_id=getDefaultCityId();
		if(isLoggedIn())
			try {
				City city;
				List<CustomersCity> customerCities = CustomersCityPeer.doSelect(new Criteria().add(CustomersCityPeer.CUSTOMERS_ID,getAppEng().getUserMgr().getCurrentCustomer().getCustomersId()));
				if(customerCities==null || customerCities.size()<1)
					city = (City) CityPeer.doSelect(new Criteria().add(CityPeer.CITY_ID,city_id)).get(0);
				else
					city = customerCities.get(0).getCity();
				getAppEng().setCity(city);
			} catch (TorqueException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return false;
			}
		else {
			//TODO: the user is not logged in so determine the users physical location 
		}
		
		return true;
	}

	private Integer getDefaultCityId() {
		Criteria c = new Criteria();
		c.add(CityPeer.CITY_NAME,"Austin");
		try {
			return ((City)CityPeer.doSelect(c).get(0)).getCityId();
		} catch (TorqueException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return -1;
	}

	@Override
	public Boolean appReset() {
			if(request.getSession().getAttribute("reset")==null) {
				setCity();
				request.getSession().setAttribute("reset", true);
				return true;
			}
			return false;
	}

	@Override
	public Boolean submitEmailToList(String email) {
		return UserManager.updateEmailList(email);
	}

	@Override
	public Boolean loginFBUser(String email) {
		try {
			List<Customers> customers = CustomersPeer.doSelect(new Criteria().add(CustomersPeer.EMAIL_ADDRESS,email));
			return (customers!=null && customers.size()>0);
		
		} catch (TorqueException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		
	}

	@Override
	public GWT_Discussion getDiscussion(String productId) {
		try {
			List<Discussion> discussions = DiscussionPeer.doSelect(new Criteria().add(DiscussionPeer.PRODUCTS_ID,Integer.parseInt(productId)));
			if(discussions!=null && discussions.size()>0)
				return helper.getGWT_DiscussionMsgs(discussions.get(0));
		} catch (NoRowsException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TooManyRowsException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TorqueException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
		
	}

	@Override
	public GWT_Message updateDiscussion(String productID, String message, Boolean addFollower) {
		try {
			Discussion discussion = (Discussion)DiscussionPeer.doSelect(new Criteria().add(DiscussionPeer.PRODUCTS_ID,Integer.parseInt(productID))).get(0);
			List<Followers> followersList = FollowersPeer.doSelect(new Criteria().add(FollowersPeer.CUSTOMERS_ID,getAppEng().getUserMgr().getCurrentCustomer().getCustomersId()).and(FollowersPeer.DISCUSSION_ID,discussion.getDiscussionId()));
			if(addFollower && followersList.size()<1)
			{
				Followers f = new Followers();
				f.setCustomers(getAppEng().getUserMgr().getCurrentCustomer());
				f.setDiscussion(discussion);
				f.save();
			}
			Message m = new Message();
			
			m.setCustomers(getAppEng().getUserMgr().getCurrentCustomer());
			m.setMessage(message);
			m.setDiscussion(discussion);
			m.setUpdateDate(new Date());
			m.save();
			
			//Email followers of this discussion
			EmailUsers.sendDiscussionEmails(discussion,m);
			//return the message for display
			return helper.getGWT_Message(m);	
		} catch (TorqueException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
		
	}

	/**
	 * Gets the product saved on the session
	 * NOTE: This method should be used only within the context of checkout
	 */
	@Override
	public GWT_Product getCurrentProduct() {
		return helper.getGWT_Product(getAppEng().getOrderMgr().getCurrentProduct());
	}

	@Override
	public GWT_Event createEvent(GWT_Event event) {
		Event e = helper.getEvent(event);
		try {
			e.setCustomers(getAppEng().getUserMgr().getCurrentCustomer());
			e.save();
		} catch (TorqueException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		} catch (Exception e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
		
		event.setId(e.getEventId());
		return event;
	}

	
	
}
